﻿using System;
using System.Linq;

using Buddy.BehaviorTree;
using Buddy.Common;
using Buddy.CommonBot;
using Buddy.Swtor;
using Buddy.Swtor.Objects;

using WingIt;
using WingIt.Dynamics;
using WingIt.Routines;
using WingIt.Routines.Mirrors;

using Action = Buddy.BehaviorTree.Action;

namespace WingIt.Routines
{//by protpally
    [RevisionControlId("$Id: Arsenal_Gunnery.cs 686 2012-08-12 16:12:20Z Chinajade $")]
    public class MercenaryArsenal_CommandoGunnery : MirrorRoutine
    {
        // MAINTAINERS NOTES:
        // * You will notice that lambda expression argument names are unique (e.g., "darkWardOn", "darkWardWhen", "joltWhen"),
        //   instead of generic (e.g., "ctx", "ret", "on", "doWhen", "castWhen").  PLEASE honor this convention!
        //   This allows us to quickly localize problems when looking at user's logs.  When the BehaviorTree encounters an exception
        //   (e.g., "object not found"), the location where an exception is thrown is identifiable only through the name
        //   of the lambda expression argument.  Such is the nature of BehaviorTrees.

        [Behavior(BehaviorType.Pull)]
        [Class(CharacterClass.BountyHunter, AdvancedClass.Mercenary, SkillTreeId.MercenaryArsenal)]
        [Class(CharacterClass.Trooper, AdvancedClass.Commando, SkillTreeId.CommandoGunnery)]
        public static Composite MercenaryArsenal_CommandoGunnery_Pull()
        {
            return new PrioritySelector(
                LazyRaider.CreateBTPS_NotifyAndShortCircuitWhenCombatDisabled(),
                CreateBTPS.BWcoreFixup_WaitForHarvestComplete(),
                TargetSelect.CreateBTPS_UpdateForBattlefieldConditions(),

                MercenaryArsenal_CommandoGunnery_Combat()
                );
        }

        [Behavior(BehaviorType.Combat)]
        [Class(CharacterClass.BountyHunter, AdvancedClass.Mercenary, SkillTreeId.MercenaryArsenal)]
        [Class(CharacterClass.Trooper, AdvancedClass.Commando, SkillTreeId.CommandoGunnery)]
        public static Composite MercenaryArsenal_CommandoGunnery_Combat()
        {
            return new PrioritySelector(
                LazyRaider.CreateBTPS_NotifyAndShortCircuitWhenCombatDisabled(),
                TargetSelect.CreateBTPS_UpdateForBattlefieldConditions(),

                #region Movement
                // Please leave these distances at 2.9f (don't use Global.Distance.Ranged)
                CreateBTPS.MoveWithinRangeAndLoS(target => MyTarget, 2.9f),
                CreateBTPS.StopWithinRangeAndLoS(target => MyTarget, 2.9f),
                #endregion

                new Decorator(lowResourcesWhen => Resource < 25,
                    new Action(burnPhaseOff => LazyRaider.BurnPhaseOff())
                ),

                #region Burn Phase
		        new Decorator(whenBurnPhaseEnabled => LazyRaider.IsBurnPhaseEnabled || MeHasConsumableBuff("Critical Boost") || MeHasConsumableBuff("Power Boost"),
                    new PrioritySelector(
                        Cast("Diversion"),
                        Cast("Full Auto", fullAutoWhen => Me.HasMirrorBuff("Curtain of Fire")),
                        Cast("High Impact Bolt", highImpactBoltWhen => Me.HasMirrorBuffStacks("Charged Barrel", 5)),
                        Cast("Demolition Round"),
                        Cast("Stockstrike", stockstrikeWhen => MyTarget.IsInRange(0.8f)),
                        Cast("Grav Round"),
                        Cast("Charged Bolts", chargedBoltsWhen => Me.CanMirrorCast("Charged Bolts", MyTarget)),
                        Cast("Explosive Round")
                    )
                ), 
                #endregion

                #region Lazyraiderish stuff - works with combat movement off
                new Decorator(whenMoving => Me.IsMoving,
                    new PrioritySelector(
                        BuffSelf("Reactive Shield", reactiveShieldWhen => Me.HealthPercent < 40),
                        Cast("Adrenaline Rush", adrenalineRushWhen => Me.HealthPercent <= 60),
                        Cast("Hammer Shot", hammerShotWhen => Resource < 75 && !(LazyRaider.IsBurnPhaseEnabled || MeHasConsumableBuff("Critical Boost") || MeHasConsumableBuff("Power Boost"))),
                        Cast("Concussion Charge", concussionChargeWhen => Resource >= 84 && Me.MobCountAround(0.4f, Mob => Mob.IsHostile) >= 2),
                        Cast("Diversion"),
                        Cast("Demolition Round", demolitionRoundWhen => Resource >= 84 || (LazyRaider.IsBurnPhaseEnabled || MeHasConsumableBuff("Critical Boost") || MeHasConsumableBuff("Power Boost"))),
                        Cast("High Impact Bolt"),
                        Cast("Sticky Grenade"),
                        Cast("Hammer Shot", hammerShotWhen => !(LazyRaider.IsBurnPhaseEnabled || MeHasConsumableBuff("Critical Boost") || MeHasConsumableBuff("Power Boost")))
                    )
                ),
                #endregion

                new Decorator(whenBurnPhaseDisabled => !LazyRaider.IsBurnPhaseEnabled || !MeHasConsumableBuff("Critical Boost") || !MeHasConsumableBuff("Power Boost"),
                    new PrioritySelector(
                        Cast("Recharge Cells", rechargeCellsWhen => Resource <= 50 && !LazyRaider.IsBurnPhaseEnabled),
                        Cast("Grav Round", gravRoundWhen => Resource >= 84 && !MyTarget.HasMirrorDebuffStacks("Gravity Vortex", 1, d => (d.TimeLeft >= TimeSpan.FromSeconds(6)))),
                        Cast("Tenacity", tenacityWhen => Me.IsStunned),
                        BuffSelf("Reactive Shield", reactiveShieldWhen => Me.HealthPercent < 40),
                        Cast("Adrenaline Rush", adrenalineRushWhen => Me.HealthPercent <= 60),
                        Cast("Diversion"),
                        Cast("Full Auto", fullAutoWhen => Resource >= 84 &&  Me.HasMirrorBuff("Curtain of Fire")),
                        Cast("Hammer Shot", hammerShotWhen => Resource < 75 && !(LazyRaider.IsBurnPhaseEnabled || MeHasConsumableBuff("Critical Boost") || MeHasConsumableBuff("Power Boost"))),
                        Cast("Concussion Charge", concussionChargeWhen => Resource >= 84 && Me.MobCountAround(0.4f, Mob => Mob.IsHostile) >= 2),
                        Cast("Stockstrike", stockstrikeWhen => Resource >= 84 && MyTarget.IsInRange(0.8f)),
                        #region PreGravRound-Low LVL Support
                        new Decorator(whenGravRoundNotKnown => !Me.HasMirrorAbility("Grav Round"),
                            new PrioritySelector(
                                Cast("Sticky Grenade", stickyGrenadeWhen => Me.MobCountAttacking() >= 3 && Resource >= 84),
                                Cast("High Impact Bolt"),
                                Cast("Full Auto", fullAutoWhen => Resource >= 84),
                                Cast("Explosive Round", explosiveRoundWhen => Resource >= 84),
                                Cast("Charged Bolts", chargedBoltsWhen => Me.CanMirrorCast("Charged Bolts", MyTarget)),
                                Cast("Hammer Shot", hammerShotWhen => !(LazyRaider.IsBurnPhaseEnabled || MeHasConsumableBuff("Critical Boost") || MeHasConsumableBuff("Power Boost")))
                            )
                        ),
                        #endregion
                        Cast("Demolition Round", demolitionRoundWhen => MyTarget.HasMirrorDebuffStacks("Gravity Vortex", 4) && Resource >= 84),
                        Cast("High Impact Bolt", highImpactBoltWhen => MyTarget.HasMirrorDebuffStacks("Gravity Vortex", 4) && Resource >= 84 && Me.HasMirrorBuffStacks("Charged Barrel", 3)),
                        Cast("Full Auto", fullAutoWhen => Resource >= 84),
                        Cast("Grav Round", gravRoundWhen => Resource >= 84),
                        Cast("Hammer Shot", hammerShotWhen => !(LazyRaider.IsBurnPhaseEnabled || MeHasConsumableBuff("Critical Boost") || MeHasConsumableBuff("Power Boost")))
                    )
                )
            );
        }

        [Behavior(BehaviorType.OutOfCombat)]
        [Class(CharacterClass.BountyHunter, AdvancedClass.Mercenary, SkillTreeId.MercenaryArsenal)]
        [Class(CharacterClass.Trooper, AdvancedClass.Commando, SkillTreeId.CommandoGunnery)]
        public static Composite MercenaryArsenal_CommandoGunnery_OutOfCombat()
        {
            // NB: Apparently, BWcore will call this routine when in combat on occasion.  It is also called while we're pulling.
            return (new PrioritySelector(
                TargetSelect.CreateBTPS_UpdateForBattlefieldConditions(),
                new Decorator(oocBuffWhen => !Me.IsMounted,
                    new PrioritySelector(
                        BuffSelf("Armor-piercing Cell"),
                        BuffSelf("Plasma Cell", plasmaCellWhen => !Me.HasMirrorAbility("Armor-piercing Cell"))
                        ))
                ));
        }
    }
}